home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Pascal / Book Demos in Pascal / HexGridPlus / HexGrid.p next >
Text File  |  1995-06-08  |  6KB  |  254 lines

  1. program HexGrid;
  2.  
  3. {$IFC UNDEFINED THINK_PASCAL}
  4.     uses
  5.         Types, QuickDraw, Fonts, Events, Packages, Menus, Dialogs, Windows,{}
  6.         OSUtils, ToolUtils, OSEvents;
  7. {$ENDC}
  8.  
  9.  
  10.     const
  11. (*Size of the array*)
  12.         kArraySizeH = 10;
  13.         kArraySizeV = 8;
  14.  
  15.     var
  16. (* Pictures*)
  17.         hexTile, altTile, thirdTile: PicHandle;
  18.  
  19.     const
  20. (* Define constants that match our hexes *)
  21.         kHorizontalSpacing = 32;
  22.         kVerticalSpacing = 26;
  23.  
  24.  
  25. {HexToP: Convert grid coordinates to screen coordinates}
  26.  
  27.     function HexToP (theHex, offset: Point): Point;
  28.     begin
  29.         HexToP.v := kVerticalSpacing * theHex.v;
  30.         if BitAnd(theHex.v, 1) = 0 then
  31.             HexToP.h := kHorizontalSpacing * theHex.h
  32.         else
  33.             HexToP.h := kHorizontalSpacing * theHex.h + kHorizontalSpacing div 2;
  34.     end; {HexToP}
  35.  
  36.  
  37. {AddToPoint: Offset a point by h,v}
  38.  
  39.     function AddToPoint (p: Point; h, v: integer): Point;
  40.     begin
  41.         AddToPoint.h := p.h + h;
  42.         AddToPoint.v := p.v + v;
  43.     end;
  44.  
  45.  
  46. {MakePoint: Like SetPt but a function}
  47.  
  48.     function MakePoint (h, v: Integer): Point;
  49.     begin
  50.         MakePoint.h := h;
  51.         MakePoint.v := v;
  52.     end;
  53.  
  54.  
  55. {GetNeighbor: Get a specified neighbor hex to a hex}
  56.  
  57.     function GetNeighbor (source: point; direction: integer): Point;
  58.     begin
  59. {Direction 0 is to the right, then clockwise}
  60.         if BitAnd(source.v, 1) = 0 then
  61.             case direction of
  62.                 0: 
  63.                     GetNeighbor := MakePoint(source.h + 1, source.v);
  64.                 1: 
  65.                     GetNeighbor := MakePoint(source.h, source.v + 1);
  66.                 2: 
  67.                     GetNeighbor := MakePoint(source.h - 1, source.v + 1);
  68.                 3: 
  69.                     GetNeighbor := MakePoint(source.h - 1, source.v);
  70.                 4: 
  71.                     GetNeighbor := MakePoint(source.h - 1, source.v - 1);
  72.                 5: 
  73.                     GetNeighbor := MakePoint(source.h, source.v - 1);
  74.                 otherwise
  75.                     SysBeep(1);
  76.             end{case}
  77.         else
  78.             case direction of
  79.                 0: 
  80.                     GetNeighbor := MakePoint(source.h + 1, source.v);
  81.                 1: 
  82.                     GetNeighbor := MakePoint(source.h + 1, source.v + 1);
  83.                 2: 
  84.                     GetNeighbor := MakePoint(source.h, source.v + 1);
  85.                 3: 
  86.                     GetNeighbor := MakePoint(source.h - 1, source.v);
  87.                 4: 
  88.                     GetNeighbor := MakePoint(source.h, source.v - 1);
  89.                 5: 
  90.                     GetNeighbor := MakePoint(source.h + 1, source.v - 1);
  91.                 otherwise
  92.                     SysBeep(1);
  93.             end;{case}
  94.     end; {GetNeighbor}
  95.  
  96.  
  97. {Dist: Calculate the squared distance between two points}
  98.  
  99.     function Dist (p1, p2: Point): Longint;
  100.     begin
  101.         Dist := (p1.h - p2.h) * (p1.h - p2.h) + (p1.v - p2.v) * (p1.v - p2.v);
  102.     end;
  103.  
  104.  
  105. {PToHex: For a point in screen coordinates, find the hex it is located in}
  106.  
  107.     function PToHex (thePoint, offset: Point): Point;
  108.         var
  109.             theHex: Point;
  110.             p1, p2, p3: Point;
  111.             h1, h2, h3: Point;
  112.             d1, d2, d3: Longint; {integer?}
  113.             junkr: rect; {debug}
  114.     begin
  115. {Find the hex in which "top rectangle" thePoint is located - not necessarily inside the hex}
  116.         theHex.v := (thePoint.v - offset.v) div kVerticalSpacing;
  117.         if BitAnd(theHex.v, 1) = 0 then
  118.             theHex.h := (thePoint.h - offset.h) div kHorizontalSpacing
  119.         else
  120.             theHex.h := (thePoint.h - kHorizontalSpacing div 2 - offset.h) div kHorizontalSpacing;
  121.  
  122. {Find the three hexes that are closest to thePoint}
  123.         h1 := theHex;                            {The lower hex}
  124.         h2 := GetNeighbor(theHex, 4);        {The upper-left hex}
  125.         h3 := GetNeighbor(theHex, 5);        {The upper-right hex}
  126.  
  127. {Get the center of each hex}
  128.         p1 := AddToPoint(HexToP(h1, offset), kHorizontalSpacing div 2, kVerticalSpacing div 2);
  129.         p2 := AddToPoint(HexToP(h2, offset), kHorizontalSpacing div 2, kVerticalSpacing div 2);
  130.         p3 := AddToPoint(HexToP(h3, offset), kHorizontalSpacing div 2, kVerticalSpacing div 2);
  131.  
  132.         moveto(p1.h, p1.v);
  133.         line(0, 0);
  134.         moveto(p2.h, p2.v);
  135.         line(0, 0);
  136.         moveto(p3.h, p3.v);
  137.         line(0, 0);
  138.         junkr.topleft := HexToP(theHex, offset);
  139.         junkr.botright := AddToPoint(HexToP(theHex, offset), kHorizontalSpacing, kVerticalSpacing);
  140.         framerect(junkr);
  141.  
  142. {Calculate the (squared) distance from thePoint to each hex center}
  143.         d1 := Dist(p1, thePoint);
  144.         d2 := Dist(p2, thePoint);
  145.         d3 := Dist(p3, thePoint);
  146. {Pick the nearest hex!}
  147.         if d1 < d2 then
  148.             if d3 < d1 then {not d2}
  149.         {d3}
  150.                 PToHex := h3
  151.             else
  152.         {d1}
  153.                 PToHex := h1
  154.         else if d2 < d3 then {not d1}
  155.     {d2}
  156.             PToHex := h2
  157.         else
  158.     {d3}
  159.             PToHex := h3;
  160.  
  161.     end; {PToHex}
  162.  
  163.  
  164.  
  165. (* Draw a tile *)
  166.  
  167.     procedure DrawHexTile (h: Integer; v: Integer; hexTile: PicHandle);
  168.         var
  169.             tileRectangle: Rect;
  170. (* Use the picture frame *)
  171.     begin
  172.         tileRectangle := hexTile^^.picFrame;
  173. (* Move it to 0,0 *)
  174.         OffsetRect(tileRectangle, -tileRectangle.left, -tileRectangle.top);
  175. (* Offset to the proper position *)
  176. (* For every other line, offset a bit extra *)
  177.         if BitAnd(v, 1) = 0 then
  178.             OffsetRect(tileRectangle, kHorizontalSpacing * h, kVerticalSpacing * v)
  179.         else
  180.             OffsetRect(tileRectangle, kHorizontalSpacing * h + kHorizontalSpacing div 2, kVerticalSpacing * v);
  181. (* Draw it *)
  182.         DrawPicture(hexTile, tileRectangle);
  183.     end; (*DrawHexTile*)
  184.  
  185.  
  186. (* Standard inits *)
  187.  
  188.     procedure InitToolbox;
  189.     begin
  190. {$IFC UNDEFINED THINK_PASCAL}
  191.         InitGraf(@qd.thePort);
  192.         InitFonts;
  193.         FlushEvents(everyEvent, 0);
  194.         InitWindows;
  195.         InitMenus;
  196.         TEInit;
  197.         InitDialogs(nil);
  198. {$ENDC}
  199.         InitCursor;
  200.     end;
  201.  
  202. (****************** Main program ******************)
  203.  
  204.     var
  205.         myWindow: WindowPtr;
  206.         windowRectangle: Rect;
  207.         h, v: Integer;
  208.         where: Point; {debug}
  209.         direction: Integer;
  210.         neighbor: Point;
  211.  
  212. begin
  213.     InitToolbox;
  214.  
  215. (*Set up the window*)
  216.     SetRect(windowRectangle, 50, 50, 50 + kArraySizeH * kHorizontalSpacing + kHorizontalSpacing div 2, 50 + kArraySizeV * kVerticalSpacing + kVerticalSpacing div 3);
  217.     myWindow := NewCWindow(nil, windowRectangle, 'Hex grid demo', true, 0, WindowPtr(-1), false, 0);
  218.     SetPort(myWindow);
  219.  
  220. (*Load the picture*)
  221.     hexTile := GetPicture(128);            (*PICT resource #128.*)
  222.     altTile := GetPicture(129);
  223.     thirdTile := GetPicture(130);
  224.  
  225. (*Draw all tiles!*)
  226.     for h := 0 to kArraySizeH - 1 do
  227.         for v := 0 to kArraySizeV - 1 do
  228.             DrawHexTile(h, v, hexTile);
  229.  
  230.     while not Button do
  231.         ;
  232.  
  233. {Demonstrate PToHex by drawing the hex in which the mouse is}
  234.  
  235.     GetMouse(where);
  236.     where := PToHex(where, Point(0));
  237.  
  238.     while Button do
  239.         ;
  240.  
  241.     DrawHexTile(where.h, where.v, altTile);
  242.  
  243. {Demonstrate GetNeighbor by drawing the neighbors as well}
  244.  
  245.     for direction := 0 to 5 do
  246.         begin
  247.             neighbor := GetNeighbor(where, direction);
  248.             DrawHexTile(neighbor.h, neighbor.v, thirdTile);
  249.         end;
  250.  
  251.     while not Button do
  252.         ;
  253.  
  254. end. (*TextGrid*)